/**
 *	The NeuroCoSA Toolkit
 *	Copyright (C) 2003-6 Stuart Meikle.
 *
 *	This is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 of the License, or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 * @author	Stuart Meikle
 * @version	2006-halloween(mk2)
 * @license	LGPL
 */
package org.stumeikle.NeuroCoSA.PubSub;
import java.io.*;

//20061127 stumeikle
//
//basic idea here is that the subscriber needs to get access to the data from the previous
//update cycle, as that data is the data which has been validated or which has made it to the
//outside world (for neurocosa).
//
//thus if the publication has current and previous values stored:
//
//if the subscriber is updated (in each cycle) before the publisher then it needs the current value 
//if the subscriber is updated after the publisher then it needs the previous value

import java.util.*;

public class YesterdaysNews extends Publication
{
    protected	Object		iPreviousValue;
    protected	long		iUpdateTime;
    protected	TimeLord	iTimeLord;

    public YesterdaysNews(TimeLord t)
    {
	iPreviousValue = null;
	iUpdateTime = 0;
	iTimeLord=t;
    }

    public synchronized void	setValue(Object av)
    {
	if (iLocker !=null)
	{
	    //if someone has locked the data then wait
	    try{ wait() ; } 
	    catch(Exception e){}
	}

	//update and store the previous value
	//BUT ! only store the previous value if the time has changed.
	//could be that this routine is called multiple times during a
	//single clock tick
	long	 now = iTimeLord.getTime();

	iVersion ++;
	if (now!=iUpdateTime)
	{
	    iPreviousValue = iValue;
	}
	iValue = av;
	iUpdateTime = now;
	notifyReaders();
    }

    public synchronized Object	getValue()
    {
	if (iLocker!=null)	//someone is updating the data currently
	{
	    //if someone has locked the data then wait
	    try{ wait() ; } 
	    catch(Exception e){}
	}

	//return yesterdays news as 's' sees it. 
	long 	t = iTimeLord.getTime();

	if ( t > iUpdateTime )
	    return iValue;
	else
	{
	    return iPreviousValue;
	}
    }

    private	void	notifyReaders()
    {
	//call the subscribers back, and give them the previous value
	if (iReaders ==null)	return;
	ListIterator	i = iReaders.listIterator(0);
	for(;i.hasNext();)
	{
	    Subscriber	s= (Subscriber) i.next();

	    s.notify( iID, iPreviousValue, iVersion );
	}
    }
}

